package io.sdl.controller;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.sdl.common.constant.UrlConstants;
import io.sdl.common.sys.dto.ConversationDTO;
import io.sdl.common.sys.dto.SdlPatientDTO;
import io.sdl.common.sys.dto.SdlSessionMessageDTO;
import io.sdl.common.sys.entity.SdlDoctorPatientSessionEntity;
import io.sdl.common.sys.entity.SdlSessionMessageEntity;
import io.sdl.common.sys.service.SdlDoctorPatientService;
import io.sdl.common.sys.service.SdlDoctorPatientSessionService;
import io.sdl.common.sys.service.SdlSessionMessageService;
import io.sdl.common.sys.vo.ConcatenatedVo;
import io.sdl.common.sys.vo.ConversationsVo;
import io.sdl.common.utils.IdPairLookupUtils;
import io.sdl.common.utils.JsonUtils;
import io.sdl.common.utils.Result;
import io.sdl.entity.RoleUserEntity;
import io.sdl.entity.SysRoleEntity;
import io.sdl.entity.TokenEntity;
import io.sdl.entity.UserEntity;
import io.sdl.service.RoleUserService;
import io.sdl.service.SysRoleService;
import io.sdl.service.TokenService;
import io.sdl.service.UserService;
import io.swagger.v3.oas.annotations.Parameter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RestController
@RequestMapping("/api/chat")
public class ApiChatController {

    @Autowired
    private SdlSessionMessageService sdlSessionMessageService;

    @Autowired
    private SdlDoctorPatientService sdlDoctorPatientService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private SdlDoctorPatientSessionService sdlDoctorPatientSessionService;

    @Autowired
    private UserService userService;

    @Autowired
    private RoleUserService roleUserService;

    @Autowired
    private SysRoleService sysRoleService;

    /**
     * 获取会话列表
     */
    @GetMapping("/sessions")
    public Result getSessions(@RequestBody String token) {
        if(token == null || token.isEmpty()){
            return new Result().error(400,"长时间未操作,请重新登录");
        }
        TokenEntity byToken = tokenService.getByToken(token);
        return new Result().ok(sdlSessionMessageService.getUserSessions(byToken.getUserId()));
    }

    // 保存消息
    @PostMapping("/save-message")
    public Result saveMessage(@RequestBody SdlSessionMessageDTO message) {
        TokenEntity byToken = tokenService.getByToken(message.getToken());

        SdlDoctorPatientSessionEntity conversation = sdlDoctorPatientSessionService.getConversation(message.getConversationId());

        SdlSessionMessageEntity sdlSessionMessageEntity = new SdlSessionMessageEntity();

        List<SdlSessionMessageEntity> entity = sdlSessionMessageService.verificationCard(message.getContent());
        //如果是患者卡片类型的消息,并且卡片存在则不需要在保存此条卡片消息
        if(message.getMessageType().equals("patient") && entity!=null){
            return new Result();
        }
        sdlSessionMessageEntity.setSessionId(conversation.getSessionId());
        sdlSessionMessageEntity.setSenderId(byToken.getUserId());
        sdlSessionMessageEntity.setReceiverId(message.getReceiverId());
        sdlSessionMessageEntity.setMessageType(message.getMessageType());
        sdlSessionMessageEntity.setContent(message.getContent());
        sdlSessionMessageEntity.setSendTime(new Date());
        sdlSessionMessageEntity.setStatus(2);
        sdlSessionMessageService.insert(sdlSessionMessageEntity);
        return new Result();
    }

    //创建会话
    @PostMapping("/save-conversation")
    public Result getConversation(@RequestBody ConversationDTO conversation) {

        TokenEntity byToken = tokenService.getByToken(conversation.getToken());
        UserEntity userEntity = userService.selectById(byToken.getUserId());
        //获取用户角色信息
        List<RoleUserEntity> roleUsersByRoleId = roleUserService.getRoleUsersByRoleId(byToken.getUserId());
        SysRoleEntity sysRoleEntity = sysRoleService.selectById(roleUsersByRoleId.get(0).getRoleId());

        IdPairLookupUtils lookup  = new IdPairLookupUtils();
        lookup.addPair(byToken.getUserId().toString(),conversation.getReceiverId().toString());
        String concatenatedId = lookup.getConcatenatedId(byToken.getUserId().toString(), conversation.getReceiverId().toString());
        //查询是否存在会话
        SdlDoctorPatientSessionEntity entity = sdlDoctorPatientSessionService.getConversation(concatenatedId);
        ConcatenatedVo concatenatedVo = new ConcatenatedVo();
        //获取用户信息
        concatenatedVo.setSenderId(byToken.getUserId());
        concatenatedVo.setAvatarUrl(UrlConstants.getProductionUrl()+userEntity.getAvatarUrl());
        //获取会话标识
        concatenatedVo.setSessionName(concatenatedId);
        if(entity == null){
            SdlDoctorPatientSessionEntity entity1 = new SdlDoctorPatientSessionEntity();
            entity1.setSessionName(concatenatedId);
            entity1.setCreateTime(new Date());
            sdlDoctorPatientSessionService.insert(entity1);
            //新会话
            concatenatedVo.setIsNew(true);
            concatenatedVo.setPatientCard(true);

            return new Result().ok(concatenatedVo);
        }else{
            //已存在的会话
            concatenatedVo.setIsNew(false);
            //获取指定会话的历史消息
            List<SdlSessionMessageDTO> historyMessages = sdlSessionMessageService.getHistoryMessages(entity.getSessionId(), conversation.getPage(), conversation.getPageSize());
            historyMessages.forEach(msg->{
                ObjectMapper mapper = new ObjectMapper();

                if(msg.getMessageType().equals("patient")){
                    SdlPatientDTO  record = null;
                    try {
                        record = mapper.readValue(msg.getContent(), SdlPatientDTO.class);
                    } catch (JsonProcessingException e) {
                        throw new RuntimeException(e);
                    }
                    //如果患者界面选择的患者(即conversation.getPatientId()存在时)跟会话之前的患者不一样则将会话标记为true,这样可以将新患者卡片发送给专家
                    if(conversation.getPatientId()!=null && !record.getPatientsId().equals(conversation.getPatientId()) ){
                        concatenatedVo.setPatientCard(true);
                    }
                    //如果是专家则可以获取所有的患者卡片
                    if(sysRoleEntity.getRemark().equals("doctor")){
                        concatenatedVo.setPatientCard(true);
                    }
                    msg.setPatientInfo(record);
                }

                });

            List<SdlSessionMessageDTO> list = historyMessages.stream().sorted(Comparator.comparing(SdlSessionMessageDTO::getSendTime)).toList();
            concatenatedVo.setMessages(list);

            return new Result().ok(concatenatedVo);
        }
    }

    //根据会话id获取历史消息
    @PostMapping("/get-messages")
    public Result getMessages(@RequestBody ConversationDTO conversation) {

        SdlDoctorPatientSessionEntity doctorPatientSession = sdlDoctorPatientSessionService.getConversation(conversation.getConversationId());
        List<SdlSessionMessageDTO> historyMessages = sdlSessionMessageService.getHistoryMessages(doctorPatientSession.getSessionId(), conversation.getPage(), conversation.getPageSize());
        List<SdlSessionMessageDTO> list = historyMessages.stream().sorted(Comparator.comparing(SdlSessionMessageDTO::getSendTime)).toList();
        return new Result().ok(list);

    }


    /**
     * 获取会话列表
     */
    @PostMapping("/messageList")
    public Result getmessageList(@RequestBody ConversationDTO conversation) {
        TokenEntity byToken = tokenService.getByToken(conversation.getToken());
        //用户作为接收人获取会话列表
        List<SdlSessionMessageDTO> msgList = sdlSessionMessageService.getMsgList(byToken.getUserId());
        ArrayList<ConversationsVo> conversationsVos = new ArrayList<>();
        msgList.forEach(msg->{
            ConversationsVo conversationsVo = new ConversationsVo();
            conversationsVo.setId(msg.getSenderId());

            UserEntity user = userService.getUserByUserId(msg.getSenderId());
            conversationsVo.setName(user.getNickName());
            //获取用户角色信息
            List<RoleUserEntity> roleUsersByRoleId = roleUserService.getRoleUsersByRoleId(user.getId());
                SysRoleEntity sysRoleEntity = sysRoleService.selectById(roleUsersByRoleId.get(0).getRoleId());
            conversationsVo.setType(sysRoleEntity.getRemark());

            conversationsVo.setAvatar(UrlConstants.getProductionUrl()+user.getAvatarUrl());
            if(msg.getMessageType().equals("patient")){
                ObjectMapper mapper = new ObjectMapper();
                SdlPatientDTO  record = null;
                try {
                    record = mapper.readValue(msg.getContent(), SdlPatientDTO.class);
                } catch (JsonProcessingException e) {
                    throw new RuntimeException(e);
                }
                msg.setPatientInfo(record);
                conversationsVo.setLastMessage(record.getName()+"的档案信息");
            } else if (msg.getMessageType().equals("text")) {
                conversationsVo.setLastMessage(msg.getContent());
            }


            conversationsVo.setLastTime(msg.getSendTime());
            conversationsVo.setUnread(msg.getUnreadMsg());
            conversationsVos.add(conversationsVo);
        });
        return new Result().ok(conversationsVos);
    }


    /**
     * 消息标记为已读
     */
    @PostMapping("/exitRead")
    public Result readMessage(@RequestBody ConversationDTO conversation) {
        TokenEntity byToken = tokenService.getByToken(conversation.getToken());

        sdlSessionMessageService.readMsg(byToken.getUserId(),conversation.getSenderId());

        return new Result();
    }

    /**
     * 获取未读消息数
     */
    @GetMapping("/unreadMsg")
    public Result getUnreadMsg(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {

        TokenEntity byToken = tokenService.getByToken((String) params.get("token"));
        if(byToken!=null){
            int unreadMsg = sdlSessionMessageService.getUnreadMsg(byToken.getUserId());

            return new Result().ok(unreadMsg);
        }
        return new Result();
    }


}
